# LeetCode 43、字符串相乘

# 一、题目描述

给定两个以字符串形式表示的非负整数 num1num2,返回 num1num2 的乘积,它们的乘积也表示为字符串形式。

**注意:**不能使用任何内置的 BigInteger 库或直接将输入转换为整数。

示例 1:

输入: num1 = "2", num2 = "3"
输出: "6"

示例 2:

输入: num1 = "123", num2 = "456"
输出: "56088"

提示:

  • 1 <= num1.length, num2.length <= 200
  • num1num2 只能由数字组成。
  • num1num2 都不包含任何前导零,除了数字0本身。

# 二、题目解析

# 三、参考代码

# 1、Java 代码

// 登录 AlgoMooc 官网获取更多算法图解
// https://www.algomooc.com
// 作者:程序员吴师兄
// 微信:wzb_3377
// 代码有看不懂的地方一定要私聊咨询吴师兄呀
// 字符串相乘(LeetCode 43):https://leetcode.cn/problems/multiply-strings/submissions/
class Solution {
    public String multiply(String num1, String num2) {

        // 边界处理,任何数和 0 相乘都为 0 
        if (num1.equals("0") || num2.equals("0")) {
            // 直接返回 0
            return "0";

        }

        // 获取字符串 num1 的长度
        int m = num1.length() ;
        
        // 获取字符串 num2 的长度
        int n = num2.length();

        // 基于这两个长度可以构造一个长度为 m + n 的数组
        // 因为假设 m = 2 ,最大数是 99
        // n = 3 ,最大数是 999
        // 两者相乘的结果 98901 长度为 5 
        int[] ansArr = new int[m + n];

        // 从后向前依次访问 num1 中的元素
        for (int i = m - 1; i >= 0; i--) {

            // '0' 的 ASCII 码是 48 ,'1' 的是 49 
            // 获取数字,相当于字符串转整数操作
            int x = num1.charAt(i) - 48 ;

            // 从后向前依次访问 num2 中的元素
            for (int j = n - 1; j >= 0; j--) {
                
                // '0' 的 ASCII 码是 48 ,'1' 的是 49 
                // 获取数字,相当于字符串转整数操作
                int y = num2.charAt(j) - 48;

                // 把 x 和 y 相乘的结果存放到 i + j + 1 位
                // 比如一开始 i = m - 1 、j = n - 1 
                // 那么就存放到 m - 1 + n - 1 + 1 = m + n - 1
                // 数组的索引是从 0 开始 ,即此时存放到了最后一位
                // 并且由于 x 和 y 必然都是个位数,相乘的结果最多只能是两位数
                ansArr[ i + j + 1 ] += x * y;

            }
        }

        // 接下来,需要把 ansArr 的每一位都拿出来查看一下
        // 使得每一个都只存放一位数字,多余的传递给上一层
        for (int k = m + n - 1; k > 0; k--) {

            // 上一位的数字需要累加当前这一位的十位数
            // 比如 ansArr[k] = 24 , ansArr[k - 1]  = 68
            // 那么 ansArr[k - 1] 需要加上 2 ,变成了 70
            ansArr[k - 1] += ansArr[k] / 10;

            // 然后 ansArr[k] 就更新为它的个位数
            ansArr[k] %= 10;
        }

        // 最后,开始把数组转换为字符串的形式
        StringBuffer ans = new StringBuffer();

        // 从最高位开始接收
        // 此时,需要判断一下 ansArr[0] 是否为 0 , 如果为 0 ,那么就抛弃这一位,从下一位在开始接收
        int index = ansArr[0] == 0 ? 1 : 0;

        // 不断的去填充字符串
        while (index < m + n) {

            // 一位一位去接收
            ans.append(ansArr[index]);

            // 再去填充下一位
            index++;
        }

        // 最后返回结果
        return ans.toString();
    }
}

# 2、C++ 代码

class Solution {
public:
    string multiply(string num1, string num2) {
        // 边界处理,任何数和 0 相乘都为 0 
        if (num1 == "0" || num2 == "0") {
            // 直接返回 0
            return "0";

        }

        // 获取字符串 num1 的长度
        int m = num1.size() ;
        
        // 获取字符串 num2 的长度
        int n = num2.size();

        // 基于这两个长度可以构造一个长度为 m + n 的数组
        // 因为假设 m = 2 ,最大数是 99
        // n = 3 ,最大数是 999
        // 两者相乘的结果 98901 长度为 5 
        auto ansArr = vector<int>(m + n);

        // 从后向前依次访问 num1 中的元素
        for (int i = m - 1; i >= 0; i--) {

            // '0' 的 ASCII 码是 48 ,'1' 的是 49 
            // 获取数字,相当于字符串转整数操作
            int x = num1.at(i) - '0' ;

            // 从后向前依次访问 num2 中的元素
            for (int j = n - 1; j >= 0; j--) {
                
                // '0' 的 ASCII 码是 48 ,'1' 的是 49 
                // 获取数字,相当于字符串转整数操作
                int y = num2.at(j) - '0';

                // 把 x 和 y 相乘的结果存放到 i + j + 1 位
                // 比如一开始 i = m - 1 、j = n - 1 
                // 那么就存放到 m - 1 + n - 1 + 1 = m + n - 1
                // 数组的索引是从 0 开始 ,即此时存放到了最后一位
                // 并且由于 x 和 y 必然都是个位数,相乘的结果最多只能是两位数
                ansArr[ i + j + 1 ] += x * y;

            }
        }

        // 接下来,需要把 ansArr 的每一位都拿出来查看一下
        // 使得每一个都只存放一位数字,多余的传递给上一层
        for (int k = m + n - 1; k > 0; k--) {

            // 上一位的数字需要累加当前这一位的十位数
            // 比如 ansArr[k] = 24 , ansArr[k - 1]  = 68
            // 那么 ansArr[k - 1] 需要加上 2 ,变成了 70
            ansArr[k - 1] += ansArr[k] / 10;

            // 然后 ansArr[k] 就更新为它的个位数
            ansArr[k] %= 10;
        }

        // 最后,开始把数组转换为字符串的形式
        string ans;

        // 从最高位开始接收
        // 此时,需要判断一下 ansArr[0] 是否为 0 , 如果为 0 ,那么就抛弃这一位,从下一位在开始接收
        int index = ansArr[0] == 0 ? 1 : 0;

        // 不断的去填充字符串
        while (index < m + n) {

            // 一位一位去接收
            ans.push_back(ansArr[index]);

            // 再去填充下一位
            index++;
        }

        // 转换为数字的形式
        for (auto &c: ans) {
            c += '0';
        }

        // 最后返回结果
        return ans;

    }
};

# 3、Python 代码

class Solution:
    def multiply(self, num1: str, num2: str) -> str:
        # 边界处理,任何数和 0 相乘都为 0 
        if num1 == "0" or num2 == "0":
            # 直接返回 0
            return "0"

        # 获取字符串 num1 的长度
        m = len(num1) 
        
        # 获取字符串 num2 的长度
        n = len(num2)

        # 基于这两个长度可以构造一个长度为 m + n 的数组
        # 因为假设 m = 2 ,最大数是 99
        # n = 3 ,最大数是 999
        # 两者相乘的结果 98901 长度为 5 
        ansArr = [0] * (m + n)

        # 从后向前依次访问 num1 中的元素
        for i in range(m - 1, -1, -1):

            # '0' 的 ASCII 码是 48 ,'1' 的是 49 
            # 获取数字,相当于字符串转整数操作
            x = int(num1[i])

            # 从后向前依次访问 num2 中的元素
            for j in range(n - 1, -1, -1):
                
                # '0' 的 ASCII 码是 48 ,'1' 的是 49 
                # 获取数字,相当于字符串转整数操作
                y = int(num2[j])

                # 把 x 和 y 相乘的结果存放到 i + j + 1 位
                # 比如一开始 i = m - 1 、j = n - 1 
                # 那么就存放到 m - 1 + n - 1 + 1 = m + n - 1
                # 数组的索引是从 0 开始 ,即此时存放到了最后一位
                # 并且由于 x 和 y 必然都是个位数,相乘的结果最多只能是两位数
                ansArr[ i + j + 1 ] += x * y



        # 接下来,需要把 ansArr 的每一位都拿出来查看一下
        # 使得每一个都只存放一位数字,多余的传递给上一层
        for k in range(m + n - 1, 0, -1):

            # 上一位的数字需要累加当前这一位的十位数
            # 比如 ansArr[k] = 24 , ansArr[k - 1]  = 68
            # 那么 ansArr[k - 1] 需要加上 2 ,变成了 70
            ansArr[k - 1] += ansArr[k] // 10

            # 然后 ansArr[k] 就更新为它的个位数
            ansArr[k] %= 10

        # 最后,开始把数组转换为字符串的形式
        

        # 从最高位开始接收
        # 此时,需要判断一下 ansArr[0] 是否为 0 , 如果为 0 ,那么就抛弃这一位,从下一位在开始接收
        index = 1 if ansArr[0] == 0 else 0

        # 不断的去填充字符串
        ans = "".join(str(x) for x in ansArr[index:])

        # 最后返回结果
        return ans